package org.jiuling.network.tools.http.request.factory.impl;

import org.jiuling.local.tools.verify.MapVerify;
import org.jiuling.local.tools.verify.ObjectVerify;
import org.jiuling.network.tools.http.request.enums.RequestMethodEnum;
import org.jiuling.network.tools.http.request.enums.SSLProtocol;
import org.jiuling.network.tools.http.request.exception.RequestException;
import org.jiuling.network.tools.http.request.factory.HttpRequestFactory;
import org.jiuling.network.tools.http.request.model.HttpRequestBody;
import org.jiuling.network.tools.http.request.model.HttpRequestHeader;
import org.jiuling.network.tools.http.request.model.HttpRequestParam;

import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
 * Http请求配置
 * @author 紫灵
 * @date 2022年11月22日 09时48分58秒
 */
abstract class HttpRequestConfig implements HttpRequestFactory {

    /** 请求方式 */
    protected RequestMethodEnum requestMethod = RequestMethodEnum.GET;

    /** 请求头 */
    protected HttpRequestHeader httpRequestHeader;

    /** 请求参数 */
    protected HttpRequestParam httpRequestParam;

    /** 请求内容 */
    protected HttpRequestBody httpRequestBody;

    /** ssl协议 */
    protected SSLProtocol sslProtocol = SSLProtocol.SSL;

    /** 链接超时事件 */
    protected Integer connectTimeout = 3000;

    /** 读取超时时间 */
    protected Integer readTimeout = 5000;

    /** 代理 */
    protected Proxy proxy;

    /** 信任管理器 */
    protected X509TrustManager x509TrustManager = new DefaultTrustManager();


    @Override
    public HttpRequestFactory setRequestMethod(RequestMethodEnum requestMethod) {
        this.requestMethod = requestMethod;
        return this;
    }

    @Override
    public HttpRequestFactory setRequestParam(HttpRequestParam httpRequestParam){
        this.httpRequestParam = httpRequestParam;
        return this;
    }

    @Override
    public HttpRequestFactory setRequestHeader(HttpRequestHeader httpRequestHeader){
        this.httpRequestHeader = httpRequestHeader;
        return this;
    }

    @Override
    public HttpRequestFactory setRequestBody(HttpRequestBody httpRequestBody){
        this.httpRequestBody = httpRequestBody;
        return this;
    }

    @Override
    public HttpRequestFactory setConnectTimeout(Integer connectTimeout){
        this.connectTimeout = connectTimeout;
        return this;
    }

    @Override
    public HttpRequestFactory setX509TrustManager(X509TrustManager x509TrustManager) {
        this.x509TrustManager = x509TrustManager;
        return this;
    }

    /**
     * 设置读取超时时间
     * @param readTimeout 读取超时时间 默认5000毫秒
     * @return http请求接口
     */
    @Override
    public HttpRequestFactory setReadTimeout(Integer readTimeout){
        this.readTimeout = readTimeout;
        return this;
    }

    @Override
    public HttpRequestFactory setProxy(Proxy proxy){
        this.proxy = proxy;
        return this;
    }

    @Override
    public HttpRequestFactory setSslProtocol(SSLProtocol sslProtocol) {
        this.sslProtocol = sslProtocol;
        return this;
    }

    /**
     * 获取URL
     * @param path 请求地址
     * @return URL
     */
    protected URL getUrl(String path) throws MalformedURLException {
        StringBuffer urlStringBuffer = new StringBuffer(path);
        if(!MapVerify.isNull(httpRequestParam)){
            urlStringBuffer.append("?");
            httpRequestParam.forEach((k,v)->{
                try {
                    urlStringBuffer.append(k).append("=").append(URLEncoder.encode(String.valueOf(v), "utf-8")).append("&");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            });
            urlStringBuffer.deleteCharAt(urlStringBuffer.length()-1);
        }

        return new URL(urlStringBuffer.toString());
    }

    /**
     * 获取远程连接
     * @param path 请求地址
     * @return 远程连接
     */
    protected URLConnection getURLConnection(String path) throws IOException {
        URL url = this.getUrl(path);
        // 开启远程连接
        return ObjectVerify.isNull(proxy) ? url.openConnection() :  url.openConnection(proxy);
    }

    /**
     * 链接
     * @param urlConnection URL链接
     * @return URL链接
     */
    protected URLConnection connect(URLConnection urlConnection) throws IOException, RequestException {
        // 设置连接超时时间
        urlConnection.setConnectTimeout(connectTimeout);
        // 设置读取超时时间
        urlConnection.setReadTimeout(readTimeout);

        // 设置请求头
        if(!MapVerify.isNull(httpRequestHeader)){
            httpRequestHeader.forEach(urlConnection::setRequestProperty);
        }

        // 设置请求内容
        if(!RequestMethodEnum.GET.equals(requestMethod) && !ObjectVerify.isNull(httpRequestBody)){
            // 设置输入实处权限
            urlConnection.setDoInput(true);
            urlConnection.setDoOutput(true);
            OutputStream outputStream = urlConnection.getOutputStream();
            outputStream.write(httpRequestBody.getBody().getBytes(StandardCharsets.UTF_8));
            // 关闭输入流
            outputStream.close();
        }else {
            // 获取连接
            urlConnection.connect();
        }
        return urlConnection;
    }

    /**
     * 默认信任管理器
     */
    class DefaultTrustManager implements X509TrustManager {
        @Override
        public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }
    }

}
